#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>
#include <iomanip>
#include "compiler/lexer.h"
#include "compiler/parser.h"
#include "compiler/semantic_analyzer.h"
#include "compiler/planner.h"
#include "execution/executor.h"
#include "execution/catalog.h"
#include "storage/buffer_pool.h"
#include "storage/disk_manager.h"

// Simplified SQL execution function
void executeSqlStatementsSimplified(const std::string& inputSql, SemanticAnalyzer& semanticAnalyzer, Executor& executor, std::shared_ptr<Catalog> catalog) {
    try {
        // Lexical analysis
        Lexer lexer(inputSql);
        std::vector<Token> tokens = lexer.tokenize();
        
        // Syntax analysis
        Parser parser(tokens);
        std::vector<std::unique_ptr<AST::Statement>> statements = parser.parseMultipleStatements();
        
        // Execute each statement
        for (const auto& stmt : statements) {
            // Semantic analysis
            semanticAnalyzer.analyze(stmt);
            
            // Execution plan generation
            Planner planner;
            std::unique_ptr<Execution::PlanNode> plan = planner.createPlan(stmt);
            
            // Execution
            ExecutionResult result = executor.execute(plan);
            
            // Get column names if it's a SELECT statement
            std::vector<std::string> columnNames;
            if (auto* selectPlan = dynamic_cast<Execution::SelectPlan*>(plan.get())) {
                TableInfo* tableInfo = catalog->getTable(selectPlan->tableName);
                if (tableInfo != nullptr) {
                    for (const auto& col : tableInfo->columns) {
                        columnNames.push_back(col.name);
                    }
                }
            }
            
            // Simplified result handling
            if (!result.success) {
                std::cerr << "Error: " << result.message << std::endl;
            } else if (!result.rows.empty()) {
                // Display query results in table format
                if (!result.rows.empty()) {
                    // Calculate column widths
                    size_t maxCols = 0;
                    for (const auto& row : result.rows) {
                        maxCols = std::max(maxCols, row.size());
                    }
                    
                    std::vector<size_t> colWidths(maxCols, 0);
                    
                    // Consider column names when calculating widths
                    for (size_t i = 0; i < columnNames.size() && i < maxCols; ++i) {
                        colWidths[i] = std::max(colWidths[i], columnNames[i].size());
                    }
                    
                    // Consider data when calculating widths
                    for (const auto& row : result.rows) {
                        for (size_t i = 0; i < row.size(); ++i) {
                            colWidths[i] = std::max(colWidths[i], row[i].size());
                        }
                    }

                    // Print top separator
                    for (size_t i = 0; i < colWidths.size(); ++i) {
                        if (i > 0) std::cout << "-+-";
                        std::cout << std::string(colWidths[i], '-');
                    }
                    std::cout << std::endl;

                    // Print column headers
                    if (!columnNames.empty()) {
                        for (size_t i = 0; i < columnNames.size() && i < colWidths.size(); ++i) {
                            if (i > 0) std::cout << " | ";
                            std::cout << std::setw(colWidths[i]) << std::left << columnNames[i];
                        }
                        std::cout << std::endl;

                        // Print header separator
                        for (size_t i = 0; i < colWidths.size(); ++i) {
                            if (i > 0) std::cout << "-+-";
                            std::cout << std::string(colWidths[i], '=');
                        }
                        std::cout << std::endl;
                    }

                    // Print rows
                    for (const auto& row : result.rows) {
                        for (size_t i = 0; i < row.size(); ++i) {
                            if (i > 0) std::cout << " | ";
                            std::cout << std::setw(colWidths[i]) << std::left << row[i];
                        }
                        std::cout << std::endl;
                    }

                    // Print bottom separator
                    for (size_t i = 0; i < colWidths.size(); ++i) {
                        if (i > 0) std::cout << "-+-";
                        std::cout << std::string(colWidths[i], '-');
                    }
                    std::cout << std::endl;
                    std::cout << "(Total " << result.rows.size() << " records)" << std::endl;
                }
            } else {
                std::cout << result.message << std::endl;
            }
        }
    } catch (const LexerError& e) {
        std::cerr << "Lexical error: " << e.what() << std::endl;
    } catch (const ParserError& e) {
        std::cerr << "Syntax error: " << e.what() << std::endl;
    } catch (const SemanticError& e) {
        std::cerr << "Semantic error: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "System error: " << e.what() << std::endl;
    }
}

int main(int argc, char* argv[]) {
    try {
        // Create necessary components
        std::unique_ptr<DiskManager> diskManager = std::make_unique<DiskManager>("test.db");
        std::unique_ptr<BufferPool> bufferPool = std::make_unique<BufferPool>(10, std::move(diskManager));
        std::shared_ptr<Catalog> catalog = std::make_shared<Catalog>(std::move(bufferPool));
        
        // Load catalog information
        catalog->loadFromStorage();
        
        // Create analyzer and executor
        SemanticAnalyzer semanticAnalyzer(catalog);
        Executor executor(catalog->getBufferPool(), catalog);
        
        if (argc > 1) {
            // Read SQL statements from file
            std::string inputSql;
            std::ifstream file(argv[1]);
            if (!file.is_open()) {
                std::cerr << "Cannot open file: " << argv[1] << std::endl;
                return 1;
            }
            std::string line;
            while (std::getline(file, line)) {
                inputSql += line + "\n";
            }
            file.close();
            
            // Execute SQL statements from file
            executeSqlStatementsSimplified(inputSql, semanticAnalyzer, executor, catalog);
        } else {
            // Simplified interactive mode
            std::cout << "=== SimpleDB2 ===" << std::endl;
            std::cout << "Enter SQL statements to execute (type 'quit' or 'exit' to quit)" << std::endl;
            
            std::string line;
            while (true) {
                std::cout << ">>> ";
                std::getline(std::cin, line);
                
                // Check for exit
                if (line == "quit" || line == "exit") {
                    std::cout << "Goodbye!" << std::endl;
                    break;
                }
                
                // Execute SQL statement
                executeSqlStatementsSimplified(line, semanticAnalyzer, executor, catalog);
            }
        }
        
        // Save catalog information
        catalog->saveToStorage();
        
        return 0;
    } catch (const std::exception& e) {
        std::cerr << "System error: " << e.what() << std::endl;
        return 1;
    }
}